import cv2 as cv

img_color = cv.imread("image/test1.png")
img_sub = cv.imread("image/test1sub.png")

# 创建SIFT 特征检测对象
sift = cv.SIFT.create()
# 计算图片的特征点
keypoints, descriptors =  sift.detectAndCompute(img_color, None)
sub_keypoints, sub_descriptors =  sift.detectAndCompute(img_sub, None)

# 获取模版图片的宽高
w, h, _ = img_sub.shape
# 宽和高的平方 得斜角的平方
c_img_tem = w**2 + h**2

# 创建暴力匹配器
bf = cv.BFMatcher()

# knn检测  k是匹配数
matchs = bf.knnMatch(descriptors, sub_descriptors, k = 2)
print(type(matchs))
# 筛选更好的匹配位置
good_match = []
good_points = []
i = 0
for m,n in matchs:
    if m.distance < n.distance * 0.6:
        good_match.append(m)
        # 特征点的读取是按X，从左到右读取
        points = keypoints[m.queryIdx].pt

        if i == 0:
            # 第一个特征点固定记录
            good_points.append(points)
            i += 1
        else:
            x = points[0]
            y = points[1]
            x_rev = good_points[i - 1][0]
            y_rev = good_points[i - 1][1]
            # 计算两点之间的斜边距离
            c = (x - x_rev) **2 + (y - y_rev)**2
            # 如果两点之间的斜边距离小于模版图片的斜边距离说明两个特征点间高度重合,就没必要记录
            if c > c_img_tem:
                # 获取最好的坐标点
                good_points.append(points)
                i += 1

# 由于特征点是按X的从左到右读取，如果y不一样可能导致过滤不精准
# 我们就遍历过滤相似的特征点
remove_set = set()
for a in range(len(good_points) - 1):
    x = good_points[a][0]
    y = good_points[a][1]
    for b in range(a + 1, len(good_points)):
        x1 = good_points[b][0]
        y1 = good_points[b][1]
        c = (x - x1)**2 + (y - y1)**2
        if c < c_img_tem:
            remove_set.add(b)

remove_list = sorted(remove_set, reverse=True)
for a in remove_list:
    good_points.pop(a)

for a in good_points:
    b = (int(a[0]), int(a[1]))
    cv.rectangle(img_color, b, b, (0, 0, 255), 2)

print(good_points)
# 绘制匹配到的特征点
dw_img = cv.drawMatches(img_color, keypoints, img_sub, sub_keypoints, good_match, None)
cv.imshow("dw_img" , dw_img)

cv.imshow("img_color", img_color)

cv.waitKey()
cv.destroyAllWindows()